import types

# 面向对象编程（基础篇章）

class Student(object):                      # 所有的类最终都会继承Object类
    def __init__(self, name, score):        # self表示创建的实例本身（创建实例的时参数必须与__init__()方法匹配）
        self.name = name
        self.score = score                  # 实例的变量名如果以__开头，就变成了一个私有变量

    def print_score(self):
        print('%s:  %s'%(self.name, self.score))

bart = Student('Bart Simpson', 95)
bart.print_score()

# Python中继承和多态的实现
class Animal(object):
    def run(self):
        print('Animal is running')

class Dog(Animal):                 # 子类函数会屏蔽父类同名函数
    def run(self):
        print('Dog is running')

class Cat(Animal):                 # 直接继承父类函数
    pass

def runtwice(animal):
    animal.run()
    animal.run()

runtwice(Animal())
runtwice(Dog())
runtwice(Cat())

# 获取对象信息
def func():
    pass

print(type(func) == types.FunctionType)
print(type(abs) == types.BuiltinFunctionType)
print(type(lambda x: x) == types.LambdaType)
print(type(x for x in range(10)) == types.GeneratorType)

print(isinstance([0, 1, 2], (list, tuple)))    # 优先使用isinstance()判断类型，可以将指定类型及其子类“一网打尽”
print(dir('ABC'))                              # 获取对象的所有属性和方法

print(len('ABC'))                              # 两种等价形式
print('ABC'.__len__())

class MyObject(object):
    def __init__(self):
        self.x = 9

    def power(self):
        return self.x * self.x

obj = MyObject()
print(hasattr(obj, 'x'))        # 测试对象是否有对应的属性
print(setattr(obj, 'y', 10))    # 设置对象的属性
print(getattr(obj, 'y'))        # 试图获取不存在的属性，会抛出AttributeError的错误

print(getattr(obj, 'z', 404))   # 获取属性'z'，如果不存在，返回默认值404
print(hasattr(obj, 'power'))    # 测试对象是否有对应的方法

func_power = getattr(obj, 'power')
print(func_power())

# 获取属性和类类型
class Person(object):
    name = 'Person'   # 类似于C++的静态成员变量

s = Person()
Person.name = 'Bob'
print(s.name)         # 实例没有name属性，获取类的name属性
print(Person.name)    # 获取类的name属性
s.name = 'Michael'    # 给实例绑定name属性
print(s.name)         # 实例的name属性屏蔽了类的name属性
del s.name            # 删除实例的name属性

# =============== 面向对象高级编程 ===============